
#include <stdio.h>
//#include "appl_to_mac.h"
#include "hs_types.h"
#include "wlan_types.h"
#include "wlan_const.h"
//#include "enc_dec_mac.h"
//#include "mac_debug.h"
//#include "seg_reassemble.h"
//#include "ping.h"
#include "wlan_mac.h"
#include "wlan_mgt.h"
#include "memtest.h"
#include "mac_globals.h"

//#include "memtest.h"
#define HEADROOM 42

//#define PRINT_TXRX

//HS_UINT8 data_pkt[MAX_PKT_SIZE];
//HS_UINT8 eth_snap_header[SNAP_LEN] = { 0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00} ;
//HS_UINT8 local_ip[IP_ALEN] = { 0, 0, 0, 0} ;

/*static HS_UINT8 ping_pkt[IP_HLEN+ICMP_HLEN] =
{
    0x45, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x40, 0x00,
    0x40, 0x01, 0xb9, 0x2a, 0xc0, 0xa8, 0x00, 0x01,
    0xc0, 0xa8, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00,
    0xbe, 0xef, 0x00, 0x00
} ;*/

//### TODO rename to std_wep_vector
static HS_UINT8 std_wep_input[78] =
{
    0x45, 0x00, 0x00, 0x4e, 0x66, 0x1a, 0x00, 0x00, 0x80, 0x11, 0xbe, 0x64, 0x0a, 0x00, 0x01,
    0x22, 0x0a, 0xff, 0xff, 0xff, 0x00, 0x89, 0x00, 0x89, 0x00, 0x3a, 0x00, 0x00, 0x80, 0xa6,
    0x01, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x45, 0x43, 0x45, 0x4a,
    0x45, 0x48, 0x45, 0x43, 0x46, 0x43, 0x45, 0x50, 0x46, 0x45, 0x45, 0x49, 0x45, 0x46, 0x46,
    0x43, 0x43, 0x41, 0x43, 0x41, 0x43, 0x41, 0x43, 0x41, 0x43, 0x41, 0x41, 0x41, 0x00, 0x00,
    0x20, 0x00, 0x01
};

#if 0 //May need this later to test tkip with the standard specified test vector
static HS_UINT8 std_tkip_input[84] =
{
	0x45, 0x00, 0x00, 0x54, 0x00, 0x00, 0x40, 0x00, 0x40, 0x01, 0xa5, 0x55, 0xc0, 0xa8, 0x0a,
	0x02, 0xc0, 0xa8, 0x0a, 0x01, 0x08, 0x00, 0x3a, 0xb0, 0x00, 0x00, 0x00, 0x00, 0xcd, 0x4c,
	0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
	0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
	0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e,
	0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37
};
#endif



//HS_UINT8 pkt_addr_g[ETH_ALEN] = { 0, 0xde, 0xad, 0xbe, 0xef, 0} ;

void LLC_to_MAC(unsigned char *packet, unsigned short len) ;
int ping_reply(char *data, unsigned short len) ;

/*int DeliverMACPktToLLC(unsigned char *data, unsigned short len)
{
    int rc = 0 ;

    ++ wext_debug_g[3] ;

#ifdef PRINT_TXRX
    {
        eth_frame_t *eth = (eth_frame_t *)&data[0] ;

        PRINT_MAC3("DeliverMACPktToLLC: delivered frame to stack [type %04x] size %d\n", (unsigned short)eth->type, len) ;
    }
#endif

    if (mac_config_g.ping_reply && ping_reply((char *)data, len))
    {
        printf("ping respond before LLC") ;
        LLC_to_MAC(data_pkt + HEADROOM, len) ;
    }
    else
    {
        rc = send_data_to_arm(data, len) ;

        if (is_group_mac(&data[0]))
        {
            dump_mem("to llc",data,len) ;
        }
    }

    mac_config_g.cycles[3] = __sb_cfsr(MACH_CYC) ;

    if (mac_config_g.packet_capture)
    {
        if (pcap_mac2llc.file == NULL)
        {
            pcap_create("mac2llc.pcap", &pcap_mac2llc) ;
        }

        pcap_write(&pcap_mac2llc, (char *)data, (HS_UINT32)len, 0, NULL) ;
    }


    if (mac_config_g.pkt_count_rx)
    {
        -- mac_config_g.pkt_count_rx ;

        if (mac_config_g.pkt_count_rx == 0)
        {
            if (mac_config_g.count_cycles) {
                printf("\nRX CC: %u\n\n", mac_config_g.cycles[3] - mac_config_g.cycles[2]) ;
            }

            printf("\n\n") ;

            print_mem_stats() ;

            osFastPause(125 * 100000);
            fprintf(stderr, "======== EXIT ========\n") ;
            exit(-98) ;
        }
    }

    return rc ;
}*/

/*int GetPktFromLLC(unsigned char *data, unsigned short *len_p)
{
    int rc, i ;

    if(mac_config_g.cycles[0] == 0)
    	mac_config_g.cycles[0] = __sb_cfsr(MACH_CYC) ;

    rc = receive_data_from_arm(data, len_p) ;

    if (mac_config_g.pkt_to_insert)
    {
        static HS_UINT16 pkt_seq = 0 ;
        static HS_UINT8  k = 0 ;

		HS_UINT32      cc_start ;

        eth_frame_t   *eth = (eth_frame_t *)&data[0] ;
        HS_UINT8      *dst_mac = &broadcast_addr_g[0] ;

        HS_UINT16     *iplen = (HS_UINT16 *)&data[ETH_HLEN+2] ;
        HS_UINT16     *ipchk = (HS_UINT16 *)&data[ETH_HLEN+10] ;

        HS_UINT16     *icmpt = (HS_UINT16 *)&data[ETH_HLEN+IP_HLEN] ;
        HS_UINT16     *icchk = (HS_UINT16 *)&data[ETH_HLEN+IP_HLEN+2] ;
        HS_UINT16     *icmps = (HS_UINT16 *)&data[ETH_HLEN+IP_HLEN+6] ;

		cc_start = __sb_cfsr(MACH_CYC) ;

        if (!mac_config_g.pkt_broadcast)
        {
            dst_mac = &pkt_addr_g[0] ;
        }

        memcpy(eth->destination_address, &dst_mac[0],       ETH_ALEN) ;
        memcpy(eth->source_address,      &local_addr_g[0],  ETH_ALEN) ;

        eth->type = 0x0800 ; /* IP type */

  /*      if (mac_config_g.wep_std_vec)
        {
            *len_p = ETH_HLEN + 78 ;

            memcpy(&data[ETH_HLEN], &std_wep_input, 78);
        }
        else
        {
            *len_p = mac_config_g.pkt_size + ETH_HLEN ;

            memcpy(&data[ETH_HLEN], &ping_pkt,  IP_HLEN+ICMP_HLEN) ;

            k &= 0xF0 ;

            for (i = ETH_HLEN + IP_HLEN + ICMP_HLEN ; i < *len_p ; ++i)
            {
                data[i] = k ;
                ++ k ;
            }

            // update IP header
            if (mac_config_g.pkt_broadcast)
            {
                memset(&data[ETH_HLEN+IP_HLEN-IP_ALEN], 0xff, IP_ALEN) ;
            }

            *iplen = mac_config_g.pkt_size ;
            *ipchk = 0 ;
            *ipchk = in_chksum((unsigned short *)&data[ETH_HLEN], IP_HLEN) ;

            *icmps = ++pkt_seq ;
            // update icmp checksum
            *icchk = 0 ;
            *icchk = in_chksum((unsigned short *)icmpt, *len_p - ETH_HLEN - IP_HLEN) ;

        }

        rc = 0 ;

        -- mac_config_g.pkt_to_insert ;

		mac_config_g.cycles[0] += __sb_cfsr(MACH_CYC) - cc_start ;
    }

    if (mac_config_g.packet_capture && *len_p > 0)
    {
        if (pcap_llc2mac.file == NULL)
        {
            pcap_create("llc2mac.pcap", &pcap_llc2mac) ;
        }

        pcap_write(&pcap_llc2mac, (char *)data, (HS_UINT32)*len_p, 0, NULL) ;
    }

#ifdef PRINT_TXRX
    {
        eth_frame_t   *eth = (eth_frame_t *)&data[0] ;

        if (*len_p > 0)
        {
            PRINT_MAC3("GetPktFromLLC: got frame [type %04x] size %d\n", (unsigned short)eth->type, *len_p) ;
        }
    }
#endif

	if (*len_p) {

		++ wext_debug_g[2] ;
	}

    return rc ;
}*/

/*
 * Name                     : Process_inputs_from_LLC
 *
 * Description              : This function gets the data from LLC (now from a file) and sends the request to
 *                            MAC layer with MA_UNITDatarequest primitive.
 *
 * Input Parameters         : NIL
 *
 * Output Parameters        : NIL
 *
 * Return Value             : HS_VOID
 *
 * Callers Graph            : control_module_STA_in_DS      [control_module_STA.c]
 *                            AP_control_module_main        [cntrl_AP_main.c]
 *
 * Call Graph               : Verify_TxTimer                [SAR2MAC_MSDU_mgt.c]
 *                            MA_UNITDATArequest            [segmentation.c]
 */

/*void
Process_inputs_from_LLC(void)
{
    HS_UINT8    *data_lp = &data_pkt[HEADROOM] ;
    HS_UINT16   len;
    HS_INT32    status;

    MACDEBUG(sprintf(mac_logmsg,"Process_inputs_from_LLC:\n"));

	//Check if the memory pool is empty, if so let linux buffer the frames
	if (head_g == NULL) {
		MACDEBUG(sprintf(mac_logmsg,"No memory for data frame\n"));
		return;
	}

    len    = MAX_PKT_SIZE ;

    status = GetPktFromLLC(data_lp, &len);

    if (status != 0)
    {
        //MACDEBUG(sprintf(mac_logmsg,"GetPktFromLLC: No packet available from LLC\n"));
        return;
    }
    else
    {
        MACDEBUG(sprintf(mac_logmsg,"GetPktFromLLC: got frame size %d\n", len)) ;
    }

    if (mac_config_g.ping_reply)
    {
        if(ping_reply((char *)data_lp, len))
        {
            printf("ping respond from LLC") ;
            DeliverMACPktToLLC(data_lp, len) ;
            return;
        }
    }

    if (len < sizeof(eth_frame_t) || len > MAX_MSDU_SIZE)
    {
        ERRORDEBUG(sprintf(error_logmsg,"GetPktFromLLC: received bad packet len (%u) from LLC\n", len));
        return;
    }

    LLC_to_MAC(data_lp, len) ;
}*/

/*void
LLC_to_MAC(unsigned char *packet, unsigned short len)
{
    Wlan_Addr_t source_addr;

    // replace second address and ETH II type with SNAP header
    memcpy(source_addr,                  &packet[sizeof(Wlan_Addr_t)], sizeof(Wlan_Addr_t)) ;
    memcpy(&packet[sizeof(Wlan_Addr_t)], eth_snap_header,              SNAP_LEN) ;

    MA_UNITDATArequest( &source_addr,
                        (Wlan_Addr_t *)&packet[0], // first address is destination
                        (HS_UINT8 *)NULL,
                        (HS_UINT8 *)&packet[sizeof(Wlan_Addr_t)],
                        (HS_UINT16)len - sizeof(Wlan_Addr_t),
                        (HS_UINT16)CONTENTION,
                        (HS_UINT8)0
                      );
}*/

/*int
ping_reply(char *data, unsigned short len)
{
    eth_frame_t   *eth = (eth_frame_t *)&data[0] ;
    struct arphdr *arp = (struct arphdr *)&data[ETH_HLEN] ;
    struct iphdr  *iph = (struct iphdr *)&data[ETH_HLEN] ;

    unsigned char *icmpt  = (unsigned char *)&data[ETH_HLEN+IP_HLEN] ;

    unsigned short *icchk = (unsigned short *)&data[ETH_HLEN+IP_HLEN+2] ;

    if (eth->type == ETH_P_IP && iph->protocol == ICMPPROTO && *icmpt == ECHO_REQ && memcmp(iph->daddr, local_ip, IP_ALEN) == 0) {

        printf("ping found \n") ;

        // switch ethernet frame addresses
        memcpy(eth->destination_address, eth->source_address, ETH_ALEN) ;
        memcpy(eth->source_address,      &local_addr_g[0],    ETH_ALEN) ;

        memcpy(iph->daddr, &iph->saddr,  IP_ALEN);
        memcpy(iph->saddr, &local_ip[0], IP_ALEN);

        *icmpt    = ECHO_REPLY ;

        // recal checksum
        *icchk = 0;
        *icchk = in_chksum((unsigned short *)icmpt, len - ETH_HLEN - IP_HLEN);

        fast_memcpy(data_pkt + HEADROOM, data, len);

        return 1 ;
    }
    else if (eth->type == ETH_P_ARP && arp->ar_op[1] == ARP_REQUEST && memcmp(arp->ar_tip, local_ip, IP_ALEN) == 0) {

        printf("arp for us \n") ;

        // switch ethernet frame addresses
        memcpy(eth->destination_address, eth->source_address, ETH_ALEN) ;
        memcpy(eth->source_address,      &local_addr_g[0],    ETH_ALEN) ;

        // loop back ARP frame
        arp->ar_op[1] = ARP_REPLY ;

        memcpy(arp->ar_tip, arp->ar_sip,  IP_ALEN) ;
        memcpy(arp->ar_sip, &local_ip[0], IP_ALEN) ;

        memcpy(arp->ar_tha, arp->ar_sha,   ETH_ALEN) ;
        memcpy(arp->ar_sha, &local_addr_g[0], ETH_ALEN) ;

        //dump_arp(data,len) ;
        fast_memcpy(data_pkt + HEADROOM, data, len);

        return 1 ;

    }

    return 0 ;
}*/
